/**
 * 
 */
package net.kaizhong.j2ee01.websocket;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @author kzuser
 *
 */
@ServerEndpoint("/chat/{userCode}")
public class ChatWebSocket
{
    private static final Logger logger = LogManager.getLogger(ChatWebSocket.class);

    private static final AtomicInteger connectionCount = new AtomicInteger(0);
    private static final Set<ChatWebSocket> connections = new CopyOnWriteArraySet<ChatWebSocket>();
    private Session session;
    private String userCode;

    public ChatWebSocket()
    {
        logger.info("开始执行构造函数 ChatWebSocket()");
        setUserCode("guest_" + connectionCount.getAndIncrement());
        logger.info("结束执行构造函数 ChatWebSocket()");
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userCode") String userCode)
    {
        logger.info("开始建立链接 ChatWebSocket.onOpen()");
        setSession(session);
        connections.add(this);
        setUserCode(userCode);
        String message = String.format("* %s %s", userCode, "has joined.");
        broadcast(message);

        logger.info("结束建立链接 ChatWebSocket.onOpen()");
    }

    @OnMessage
    public void incoming(String message)
    {
        logger.info("开始处理消息 ChatWebSocket.incoming()");
        
        String filteredMessage = String.format("* %s: %s", getUserCode(), message);
        broadcast(filteredMessage);

        logger.info("结束处理消息 ChatWebSocket.incoming()");
    }

    @OnClose
    public void onClose(Session session, CloseReason reason)
    {
        logger.info("开始关闭链接 EchoWebSocket.onClose()");
        connections.remove(this);
        String message = String.format("* %s %s", getUserCode(), "has disconnected.");
        broadcast(message);

        logger.info("结束关闭链接 EchoWebSocket.onClose()");
    }

    @OnError
    public void onError(Session session, Throwable error)
    {
        logger.info("开始异常处理 EchoWebSocket.onError()");
        logger.info("结束异常处理 EchoWebSocket.onError()");
    }

    private void broadcast(String msg)
    {
        for (ChatWebSocket client : connections)
        {
            try
            {
                synchronized (client)
                {
                    client.session.getBasicRemote().sendText(msg);
                }
            }
            catch (IOException e)
            {
                logger.debug("Chat Error: Failed to send message to client", e);
                connections.remove(client);
                try
                {
                    client.session.close();
                }
                catch (IOException e1)
                {
                    // Ignore
                }
                String message = String.format("* %s %s", client.userCode, "has been disconnected.");
                broadcast(message);
            }
        }
    }

    public Session getSession()
    {
        return session;
    }

    public void setSession(Session session)
    {
        this.session = session;
    }

    public String getUserCode()
    {
        return userCode;
    }

    public void setUserCode(String userCode)
    {
        this.userCode = userCode;
    }

}
